/*
*    Phantom Test Driver v2.0 GUI Automation Software
*    Copyright (C) 2009  John C. Van Arsdall (john@phantomtest.com)
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/*
 * PTDConsole.java
 *
 * Created on September 22, 2005, 10:09 PM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */

package ptd;

import java.net.*;
import java.io.*;
import java.awt.event.*;
import javax.swing.text.*;
import java.util.Vector;

import ssi_colorizer.*;
import ssi_socket.*;


/**
 *
 * @author John
 */
public class PTDConsole extends SSI_ColorPane implements PTDScriptComm, PTDDisplay{
    private PTDScriptThread MainThread;
    private Socket MainSocket;
    private PrintWriter out;
    public boolean bLineAvailable;
    private int SegmentPosition;
    private MyCmdTracker CmdTracker;
    public int CmdLock;
    

    // MYCMDTRACKER ////////////////////////////////
    class MyCmdTracker {
        public Vector<String> m_CmdHist;
        public int m_Count;
        public int m_CurrInd;
        
        // -----------------------------------------------------
        public MyCmdTracker(){
            m_CurrInd = 0;
            m_Count = 0;
            m_CmdHist = new Vector<String>();
        }
        
        // -----------------------------------------------------
        public int addCmd(String s){
            if(s.length() <= 0){ // Dont add a command of length zero (empty)
                return m_Count;
            }
            if(m_CmdHist.add(s)){
                m_Count = m_CmdHist.size();
                m_CurrInd = m_Count + 1; // So when you go up, goes to last item
                return m_Count;
            }else{
                return -1;
            }
        }
        
        // -----------------------------------------------------
        public int getCount(){
            m_Count = m_CmdHist.size();
            return m_Count;
        }

        // -----------------------------------------------------
        public String cycleUp(){
            if(m_Count == 0){
                return "";
            }
            m_CurrInd = m_CurrInd - 1;
            if(m_CurrInd <= 1){
                m_CurrInd = 1;
            }
            
            String Ret = "";
            Ret = (String)m_CmdHist.get(m_CurrInd - 1);
            return Ret;
        }
        
        // -----------------------------------------------------
        public String cycleDown(){
            String Ret = "";
            
            m_CurrInd = m_CurrInd + 1;
            if(m_CurrInd > m_Count){
                m_CurrInd = m_Count;
                return "";
            }
            
            Ret = (String)m_CmdHist.get(m_CurrInd - 1);
            return Ret;
        }
        
    }
    
    // MYKEYLISTENER ////////////////////////////////
    class MyKeyListener extends java.awt.event.KeyAdapter{
        private PTDConsole pW;
        
        // -----------------------------------------------------
        public MyKeyListener(PTDConsole InConsole){
            pW = InConsole;
        }
        
        // -----------------------------------------------------
        public void keyTyped(KeyEvent e) {
            
        }
        
        // -----------------------------------------------------
        public void keyPressed(KeyEvent e) {
            
            if(e.isControlDown()){
                if((e.getKeyCode() == e.VK_V) && (pW.CmdLock == 1)){
                    e.consume();
                }

                // Dont want to consume event if control is pressed, yo...
                return;
            }
            
            if(e.isAltDown()){
                // Dont want to consume event if alt is pressed, yo...
                return;
            }
            
            // If the input is locked (information is being displayed)
            // do not allow an event to be passed to the console.
            if(pW.CmdLock == 1){
                Main.debug_out("Command Locked... consuming event");
                e.consume();
                return;
            }
            


            
            // We dont want caretPosition... this is not a character position (doesnt include new lines, maybe tabs)
            //int CurrPos = pW.getCaretPosition();
            int CurrPos = pW.getSelectionStart();  // This doesnt work either...
            if(e.getKeyCode() == e.VK_ENTER){                
                // A command was entered, so lock the input
                // This wont get cleared until the script thread requests
                // a new command.
                pW.CmdLock = 1;
                pW.setCaretPosition(pW.getDocument().getLength());
                pW.bLineAvailable = true;
            }else if(e.getKeyCode() == e.VK_UP){
                String s = CmdTracker.cycleUp();
                setCommand(s);
                e.consume();
            }else if(e.getKeyCode() == e.VK_DOWN){
                String s = CmdTracker.cycleDown();
                setCommand(s);
                e.consume();
            }else if(e.getKeyCode() == e.VK_LEFT){
                if(CurrPos <= SegmentPosition){
                    e.consume();
                }
                // Check against minimum location
            }else if(e.getKeyCode() == e.VK_HOME){
                e.consume();
                pW.setCaretPosition(SegmentPosition);
            }else if(e.getKeyCode() == e.VK_BACK_SPACE){
                if(CurrPos <= SegmentPosition){
                    e.consume();
                }
            }
            
            if(CurrPos < SegmentPosition){
                pW.setCaretPosition(pW.getDocument().getLength());
            }
        }

        // -----------------------------------------------------
        public void keyReleased(KeyEvent e) {
        }
    }
    // END MYKEYLISTENER ////////////////////////////////

    // -----------------------------------------------------
    public PTDConsole() {
        
        CmdTracker = new MyCmdTracker();
        SegmentPosition = 0;
        CmdLock = 0;
        bLineAvailable = false;
        PrintName = "PTD Console";
        this.addKeyListener(new MyKeyListener(this));
    }
    
    // -----------------------------------------------------
    public void StartThread(){
        MainThread = new PTDScriptThread(this, this, false);
        MainThread.init(true);
        MainThread.start();        
    }
    
    // -----------------------------------------------------
    public void Kill(){
        if(MainThread != null){
            MainThread.Kill();
        }
    }
    
    // -----------------------------------------------------
    public String getNextLine(){
        String Ret = "";

        // Lock the input once a line is available
        // This wont get reset until an input is requested.
        CmdLock = 1;
        
        Document aDoc = this.getDocument();
        try{
            Ret = aDoc.getText(SegmentPosition, aDoc.getLength() - SegmentPosition);
            SegmentPosition = aDoc.getLength();
        }catch (Exception e){
            Main.debug_out(e.getMessage());
        }
        
        // cut-off and remove at first newline
        int i = Ret.indexOf("\n", 0);
        if(i >= 0){
            Ret = Ret.substring(0, i);
        }
        CmdTracker.addCmd(Ret);

        bLineAvailable = false;
        return Ret;
    }
    
    // -----------------------------------------------------    
    public void setCommand(String newCmd){
        String s;
        Document aDoc = this.getDocument();
        try{
            aDoc.remove(SegmentPosition, aDoc.getLength() - SegmentPosition);
            setCaretPosition(getDocument().getLength());
            addText(newCmd);
        }catch (Exception e){
            Main.debug_out(e.getMessage());
        }
    }
    
    // -----------------------------------------------------    
    public int display(String Output){
               
        if(Output.length() <= 0) return 1;  // So buffer blank buffer doesnt accidentally destroy segment position
        
        // Lock out commands while displaying.
        // This wont get unlocked until the thread requests an input
        CmdLock = 1;
        
        getCaret().setVisible(false);
        addText(Output);
        if(hasFocus()){
            getCaret().setVisible(true);
        }
        
        Document aDoc = this.getDocument();
        try{
            SegmentPosition = aDoc.getLength();
        }catch (Exception e){
            Main.debug_out(e.getMessage());
        }
        
        return 1;
    }
    
    public int startSuite(String Name){
        return 0;
    }
    
    public int startTestcase(String Name){
        return 0;
    }

    public int startScript(String Name){
        return 0;
    }    
    
    public int displayError(String Output){
        return display(Output);
    }
    
    public int displayWarning(String Output){
        return display(Output);
    }
    
    public int displayFailure(String Output){
        return display(Output);
    }
    
    public int displayFormatted(String Output){
        return display(Output);
    }
            
    // -----------------------------------------------------    
    public boolean lineAvailable(){
        // The console will not accept input of any sort until the thread requests it
        // Part of 'double-enter' bug fix
        CmdLock = 0;
        return bLineAvailable;
    }
    
    // -----------------------------------------------------    
    public void reportFault(int iCode, String Message){
        addText(Message);
        SegmentPosition = getText().length();
    }
    
    public int requestDebug(String LineInfo){
        return 0;
    }
    
    public String getDebugCmd(){
        return "";
    }
    
    public int displayDebug(String Output){
        return 0;
    }
    
    public void setRunState(int newState){
        
    }
    
}
